/**
 * 
 */
package com.usc.nearbyus;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.wifi.ScanResult;
import android.util.Log;

/**
 * The main class that interacts with SQLiteDatabase
 * Main task - store / retrieve readings retrieved from the wi-fi scanresults
 * 
 * @author pranav
 *
 */
public class ReadingsDbAdapter {

	private final Context mCtx;
	private ReadingsDbHelper mDbHelper;
	private SQLiteDatabase mDb;

	private static final String DATABASE_NAME = "nearbyus";
	private static final int DATABASE_VERSION = 2;
	private static final String DATABASE_TABLE = "readings";
	public static final String DATABASE_CREATE = 
		"create table "+DATABASE_TABLE+" (_id integer primary key autoincrement, " +
		"longitude text not null, latitude text not null, timestamp text not null, userid text not null, isflagged text not null, " +
		"bssid text not null, ssid text not null, capabilities text not null, frequency text not null, level text not null);";

	public static final String TAG = "ReadingsDbAdapter";

	public static final String KEY_ROWID = "_id";
	public static final String KEY_LONGITUDE = "longitude";	
	public static final String KEY_LATITUDE = "latitude";
	public static final String KEY_TIMESTAMP = "timestamp";
	public static final String KEY_USERID = "userid";
	public static final String KEY_ISFLAGGED = "isflagged";
	public static final String KEY_BSSID = "bssid";
	public static final String KEY_SSID = "ssid";
	public static final String KEY_CAPABILITIES ="capabilities";
	public static final String KEY_FREQUENCY = "frequency";
	public static final String KEY_LEVEL = "level";

	/**
	 * inner class that creates DB if not created,
	 * Handles the update of Database
	 * 
	 * @author pranav
	 *
	 */
	private static class ReadingsDbHelper extends SQLiteOpenHelper{			

		public ReadingsDbHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {

			db.execSQL(DATABASE_CREATE);

		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
					+ newVersion + ", which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
			onCreate(db);

		}

	}

	/**
	 * Constructor - takes the context to allow the database to be
	 * opened/created
	 * 
	 * @param ctx the Context within which to work
	 */
	public ReadingsDbAdapter(Context mCtx) {
		super();
		this.mCtx = mCtx;
	}


	/**
	 * opens up "nearbyus" database...
	 * If it cannot be opened, try to create a new
	 * instance of the database. If it cannot be created, throw an exception to
	 * signal the failure.
	 * 
	 * @return this (self reference, allowing this to be chained in an
	 *         initialization call)
	 * @throws SQLException if the database could be neither opened or created
	 */
	public ReadingsDbAdapter open() {
		mDbHelper = new ReadingsDbHelper(mCtx);
		mDb = mDbHelper.getWritableDatabase();
		return this;	
	}

	public void close() {
		mDbHelper.close();
	}




	/**
	 * Creates an entry for the wifi-scan Reading in the database.
	 * 
	 * @param longitude
	 * @param latitude
	 * @param timestamp
	 * @param userid
	 * @param isflagged
	 * @param scanResult
	 * @return rowId or -1 if failed
	 */
	public long createReading(double longitude, double latitude, String timestamp, String userid, boolean isflagged, ScanResult scanResult ){

		ContentValues readingValues = new ContentValues();
		readingValues.put(KEY_LONGITUDE, String.valueOf(longitude));
		readingValues.put(KEY_LATITUDE,	String.valueOf(latitude));
		readingValues.put(KEY_TIMESTAMP, timestamp);
		readingValues.put(KEY_USERID, userid);
		readingValues.put(KEY_ISFLAGGED, String.valueOf(isflagged));
		readingValues.put(KEY_BSSID, scanResult.BSSID);
		readingValues.put(KEY_SSID, scanResult.SSID);
		readingValues.put(KEY_CAPABILITIES, scanResult.capabilities);
		readingValues.put(KEY_FREQUENCY, String.valueOf(scanResult.frequency));
		readingValues.put(KEY_LEVEL, String.valueOf(scanResult.level));

		Log.d(TAG, " Reading to be inserted in database : " + readingValues.toString());

		return mDb.insert(DATABASE_TABLE, null, readingValues);

	}

	/**
	 * Delete the wi-fi scan reading with the given rowId from the database table
	 * 
	 * @param rowId id of reading to delete
	 * @return true if deleted, false otherwise
	 */
	public boolean deleteNote(long rowId) {

		return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
	}


	/**
	 * This method retrieves all the readings from the database
	 * 
	 * @return Cursor - of all the readings present in database
	 */
	public Cursor getAllReadings(){

		return mDb.query(DATABASE_TABLE, 
				new String[] {KEY_ROWID, KEY_LONGITUDE, KEY_LATITUDE, KEY_TIMESTAMP, KEY_USERID, KEY_ISFLAGGED, 
				KEY_BSSID, KEY_SSID, KEY_CAPABILITIES, KEY_FREQUENCY, KEY_LEVEL}, null, null, null, null, null);
	}



	/**
	 * gets a single entry from the database for the rowId
	 * 
	 * @param rowId - of the reading
	 * @return Cursor - over the element in the database requested
	 */
	public Cursor getReading(long rowId){   

		Cursor mCursor = mDb.query(true, DATABASE_TABLE, 
				new String[] {KEY_ROWID, KEY_LONGITUDE, KEY_LATITUDE, KEY_TIMESTAMP, KEY_USERID, KEY_ISFLAGGED, 
				KEY_BSSID, KEY_SSID, KEY_CAPABILITIES, KEY_FREQUENCY, KEY_LEVEL}, 
				KEY_ROWID + "=" + rowId, null, null, null, null, null);
		if (mCursor != null) {
			mCursor.moveToFirst();
		}
		return mCursor;
	}

	/**
	 * Updates the wi-fi scan "reading" record in the database for the given rowId
	 * 
	 * @param rowId
	 * @param longitude
	 * @param latitude
	 * @param timestamp
	 * @param userid
	 * @param isflagged
	 * @param scanResult
	 * @return true if the note was successfully updated, false otherwise
	 */
	public boolean updateReading(long rowId,int longitude, int latitude, String timestamp, String userid, boolean isflagged, ScanResult scanResult){

		ContentValues readingValues = new ContentValues();
		readingValues.put(KEY_LONGITUDE, String.valueOf(longitude));
		readingValues.put(KEY_LATITUDE,	String.valueOf(latitude));
		readingValues.put(KEY_TIMESTAMP, timestamp);
		readingValues.put(KEY_USERID, userid);
		readingValues.put(KEY_ISFLAGGED, String.valueOf(isflagged));
		readingValues.put(KEY_BSSID, scanResult.BSSID);
		readingValues.put(KEY_SSID, scanResult.SSID);
		readingValues.put(KEY_CAPABILITIES, scanResult.capabilities);
		readingValues.put(KEY_FREQUENCY, String.valueOf(scanResult.frequency));
		readingValues.put(KEY_LEVEL, String.valueOf(scanResult.level));

		Log.d(TAG, " update entry in database : " + readingValues.toString());

		return mDb.update(DATABASE_TABLE, readingValues, KEY_ROWID + "=" + rowId, null) > 0;
	}

}
